{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "QEPPI.ipynb",
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jyJ3Yev3hzwQ"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/AspirinCode/QEPPI-community/blob/main/notebook/QEPPI.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3Ezk4xyjiVNV"
      },
      "source": [
        "## Notes\n",
        "\n",
        "This notebook is designed to be run in **Colab (Google Colaboratory)**, not in your local Jupyter Notebook environment.\n",
        "\n",
        "So, if you want to run it locally, please rewrite the PATH settings of each cell and the file input/output code appropriately."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "XirDETzAV0s4",
        "outputId": "d7e12934-df17-48a1-8796-0b4b6ea3b786",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!pip install rdkit\n",
        "from rdkit import rdBase\n",
        "from rdkit import Chem\n",
        "from rdkit.Chem import Draw\n",
        "print(rdBase.rdkitVersion)"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Collecting rdkit\n",
            "  Downloading rdkit-2025.3.2-cp311-cp311-manylinux_2_28_x86_64.whl.metadata (4.0 kB)\n",
            "Requirement already satisfied: numpy in /usr/local/lib/python3.11/dist-packages (from rdkit) (2.0.2)\n",
            "Requirement already satisfied: Pillow in /usr/local/lib/python3.11/dist-packages (from rdkit) (11.2.1)\n",
            "Downloading rdkit-2025.3.2-cp311-cp311-manylinux_2_28_x86_64.whl (35.2 MB)\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m35.2/35.2 MB\u001b[0m \u001b[31m14.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hInstalling collected packages: rdkit\n",
            "Successfully installed rdkit-2025.3.2\n",
            "2025.03.2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "W9iCv8X5GxSd",
        "outputId": "9bb669b2-2a35-4439-aa29-bf8444de754c",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!git clone https://github.com/AspirinCode/QEPPI-community"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Cloning into 'QEPPI-community'...\n",
            "remote: Enumerating objects: 7417, done.\u001b[K\n",
            "remote: Counting objects: 100% (25/25), done.\u001b[K\n",
            "remote: Compressing objects: 100% (25/25), done.\u001b[K\n",
            "remote: Total 7417 (delta 9), reused 0 (delta 0), pack-reused 7392 (from 4)\u001b[K\n",
            "Receiving objects: 100% (7417/7417), 1.63 MiB | 3.20 MiB/s, done.\n",
            "Resolving deltas: 100% (4874/4874), done.\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Bo609XfrOINp"
      },
      "source": [
        "#Move the working directory to path\n",
        "import os\n",
        "path = \"/content/QEPPI-community\"\n",
        "os.chdir(path)"
      ],
      "execution_count": 3,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "510NKIkmlFPn"
      },
      "source": [
        "# Calculation QEPPI for Your \"SMILES\"\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RLZj8WajlikM",
        "outputId": "89b3b6ef-fc8c-4c5d-fcb3-dbf2d283bc00",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 439
        }
      },
      "source": [
        "#@markdown ##### Example SMILES: **Idasanutlin** is a potent and selective p53-MDM2 inhibitor\n",
        "#@markdown ##### Replace with the \"SMILES\" you are interested in.\n",
        "SMILES = \"COC1=CC(=CC=C1NC(=O)[C@@H]1N[C@@H](CC(C)(C)C)[C@@](C#N)([C@H]1C1=CC=CC(Cl)=C1F)C1=CC=C(Cl)C=C1F)C(O)=O\" #@param {type:\"string\"}\n",
        "if len(SMILES) == 0:\n",
        "    print(\"Please enter SMILES.\")\n",
        "else:\n",
        "    !python calc_QEPPI.py --smiles '$SMILES'\n",
        "mol = Chem.MolFromSmiles(SMILES)\n",
        "img = Draw.MolToImage(mol)\n",
        "img"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "QEPPI.model LOADING...\n",
            "[04:40:25] SMILES Parse Error: syntax error while parsing: $SMILES\n",
            "[04:40:25] SMILES Parse Error: check for mistakes around position 1:\n",
            "[04:40:25] $SMILES\n",
            "[04:40:25] ^\n",
            "[04:40:25] SMILES Parse Error: Failed parsing SMILES '$SMILES' for input: '$SMILES'\n",
            "$SMILES is not valid, because it can't be converted to MOL. Please confirm it\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<PIL.PngImagePlugin.PngImageFile image mode=RGB size=300x300>"
            ],
            "image/png": "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\n",
            "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAEsASwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKjuJ4rW2luJnCRRIXdj2UDJP5UDSbdkSUVVuNRtLV5EmmCuioxUAk/OSFwB1JKkYHPFSWt1DeRebA+5QSpyCCpHUEHkH2NK62KdOSXM1oTUUUUyAooooAKK5rxJ8QPC/hG7itdc1ZLW4lTzEj8qSRiucZwinAyD19DWJ/wufwW//HveXtz6eVYTHP5qKAPQKK8//wCFvaM//HvoviS59PJ0xzn88VseFfHem+LLy9soLTULC9swrSWuowCGUq3RguTx/iPUUAdRRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUVTu7ieO5ghhA+dWYnZuPBX3HrVynYlSTbXYKKK4jxPq+oXHj/w14Z0q6eAlm1HUXj6/Z0yAh9nYkfgKRR29FFFABRRRQAUUUUAFFFFABVTVbNtQ0i9slYI1xBJEGPQFlIz+tW6KTV1YqMnGSkt0YMnh9o9Qa8tJjuXyWjWeR5MsnmggkkkAiXjHQjOKTSdQgj17UdLncrqUhW8dduEZSqoNhPLYCLk8ck/hv1zHjLSria1h1rS0Y6tpZM0KoMmZP4osd8joPX0zWco8usUdlGsqzcK8t1ZPt2v5aa/edPRWR4Z8Q2Xirw9aaxYsfKuEyUP3o3HDIfcHIrXrU4QqG8u4LCynvLqRYreCNpZXboqqMk/kKmrzD4s6zFcm18J+eYredDf6vKh5isojkj6uw2j3470Acz4V1XV9a+INrqdqFi1HW5DezmSMObTSo/ljj56GQ85Hop717rXn/wr0aVNKufE9/AIb/W2WVIgOLe1UYhiHoAuD+I9K9AoAK8D1r+3fC/jZ5GnlvNY03zL3T55Wy2paexLTWzHu8fLD2zgcLXvlcp4+8LS+JNESTT5PI1vTpBdadcdCsq/wk/3Wxg9uh7UAbmi6xZ6/o1pquny+Za3UYkjbv7g+hByCPUVfrxD4d+LINC1dYJgLPQ9amcLDIdo03UF/wBbAc/dVuq59QPWvWpfE/h+DPna5pkeP793GP5mgDVorBl8b+FIc7/Emk5HYXkZP6Gq0fjfT7i5mjtl86ISQpBOjgpOJGjVip/2fNXI754746Vg67+w/uFzI6eisHSvFdhq81hBbSRPNdW7zvGkys0O3b8rAc5+b9K3qyqUp03yzVmCdwooorMYUVzWpeKGsLnUYPs7s9tJCsbLBIyEPtzuYDA6nqRVG38eRQmL+2Ps9igMjSyMTt8vdiNx9TlT7qe2K644GvKPNGN/+GuTzI7Oiqlhqmn6rD52n31tdxf34JVcfoat1yyi4u0lZlBWdrmuad4c0ifU9UuVgtYRksepPYAdyfSo/EXiLTfC+kSalqc2yJflRFGXlc9ERe7H0/pXmsfgjXfiXq8Wt+N/M0/R4m3WeiRthtvrIexPGe/UfLxSA39A+Lvg7xOAkWpDTb5lKol+ojYZ9GJKnkDjPbpXW6HfPe2G2dgbmBjHLjuR3/EVFP4T8PXWjxaTPo1jJYRLtjgaFSqe6+h9xzXmHibRNX8BeIdAh8Ka0+l6NfytaeXcL58UU5yUVt3zbW6DklcHHpVJq1mZShL2ilF6df67/oezEhQSSABySa88+G4Ov6v4h8byglNSufstgT2tYflBHpuYEn3Fc7448b+NdD8JX2m674cjiu71PsltqenTb4HZ+D8h+dTt3Y7k9q1vDXxS+Huh6FYaKuqy2gs4FhC3FnKhJA5JwpGScnr3qTU9QorirT4teB77VLXTrXXY5bi5cRxgQyBSxOACxXAya7WgAooooAKKKKACiiigAooooAKZNNHbwyTTOqRRqXd2OAoAySafXE/ES6W70+Pw0sxi/tJWN3KpwYbVRmRvyGPfkVMpKKuzahQnXn7OG/8AlqeX+Gte8V/8JjP/AMIhFpkNn4muJ7yCzvEkIgiQ7ftDBSNu8g+uSOnSvR/7O+Kcv39f8OQf9crORsf99Gj4beHkgN74lkj2PqCpDZRFcfZrOMbY4x9cZJ78Gu/pppq6IqU5U5uEt1ozgP8AhG/iRN9/x/aQf9cdGjb/ANCNcinhYQ+O7/w943v5tRbxCkEtrqiKIPtHkHLW7KMhR0OB1wO5GPba5zxv4WTxZ4dks0l+z38Li4sbkcGCdeVYH07H2NMg6JVVFCqoVQMAAYAFLXLeA/FL+J9CJvY/s+sWMhtdRtjwY5l4Jx6HqPxHaupoAKKKyPFHiC28LeGr/WrvmO1iLBM4Lv0VR7kkD8aAOD8RaXYeMPiJB4Ut7SFdLsH/ALU1tokC+dMylY42I5JIJJ9Qfauoi+GfgmH7vhjTD/vwBv55qH4b+H7nRvDjXuqfNrWrSm+v2I5DvyE9gowMdjmuxoAxY/B/hiI5j8O6Sp9RZR5/lVXWPDNsdJuTpllD9rjmS9tYidkYnjUBBxjCnaAR3ya6SiuiOKrKSlzN+rYuVHJ+CLvT9d0DS76COSG40+J7OW3dvmhk+UOrD/gII9jXWV5x4jkf4f8Ai+LxRCmNB1SRbfWFAOIJDwk+PTJw3+Jr0ZWV1DKQykZBByCKMVOE6rlTvZ9+l9Wvk29eoRTS1Fooqtf39tpen3F/ezLDbW8ZklkboqgZJrnGcr481NdL0/7BpttHNrmtyrDbRkZywx+8b2QAH06Z4zW7a6BZCyso762trq4t4DEZWiGG3YL4XoAxGcVyngG1vPEWo3PjvV4jG96DHpVs4Gba17H/AHn6/Q8fer0GuueISpQp07prVvrfb7kv1JtrdnIX/wAMfCt5P9pgsG026H3Z9OkMDL9APl/Ssa78NeN/DFlcXeieNH1G3t42k+x6zbiUsFBOPNXDZ49q9IqC9i8+xuIf78TL+YxWNWvVq29pJu213caSWxx/gi3TxPpem+M9YVbjVLmHdCp/1VoucYiU9CcDLHLH1xgV29cN8HZfO+E+gN6RyL+Urj+ldzWQwrzz4vsL3w1Y+HYUV9Q1nUIbe2J6xYYM0nH90Dk/7Veh153p3/FU/GPUNRPz2Hhq3+xW57G5k5kYe4X5T+FAHmPjfwXqsfi/SNEFpqOppdXZ+z3Ws6yZlvAibnBRQGjAzgnrxwa6mx+EevbQGTwdpXvbaUbxl/GfPNdTrn+m/G7wrb9fsGn3d3j034jz+legUAcFY/DGEeGdR0PWtVk1O3vApQC2jt1tnXcd8SoMKctn8PrS+CPEWoWuozeC/E8mdbsU3W1yeBf2/wDDIPVgOGHXj647yuW8ceEf+En06Gayn+x63p7+fp14vWOQfwn/AGW6EfzxigDqaK4DRPipojaQR4mvLfRtZtXMF7ZzthlkXqVHUqeoIz1xV7T/AIneGtZklTR5bzUTFjd9ntJMc+m4DPSplJRV3sTOcYR5pPQ7GiucbX9SuIZjb6FewKInYTTgAqQpI+Tqee1XLSdG1OBINQa7iaCVmPmKwDAx46D3P51mq8Zbf5fmYxxMJP3f8vzNeiiitjoCiiigCK4uI7W2luJm2xRIXc+gAya4fVfDr69q024z2k+oJEZROyt/oqMN8cZX7pJKEg569etd1NDHcQSQSqHjkUo6nuCMEVUtNMW1nE73NxcyLH5SNMV+RMgkDAHXAyTk8CsqkOfR7HbhMT9XvODtL+mvxWt/kXIo0hiSKNQkaKFVQOAB0FOoorU4m7hRRRQB554s0rV/DviyDxl4Y02TUHuFFrq2nxMFM6fwSDP8SnA78Y7ZNcF/wj3jC4Of7G8e3Ge1z4qhjH/oHFfQFFAHz/8A8IF4ouP9Z4P1A/8AX34q3/8AoIFTXGm6rod14U03xRpVvpnhSLU/MYQXbXIacgmPzWY8Lu/DrntXvVZ2vaJZeI9Du9I1CPfbXUZRvVT2Ye4OCPcUAaNFcj4Hvrq2tpPDOrztLqmlKE85utxD/DIPwwD+GeTXXUoyUldGlWjOlLlmtdH9+qCiiqGsXk9npsz2aRy3xQi3heQL5j9hyRQ3ZXJhBzkorqeb/FjXkvQ/htpJINIgjF3rd2g+7ECCkCHp5jttGO2R2zWr8PfDurHQbK+1q5mh32k0Ftp/X7LbSeVsQsfmLKIupyfnI7VQ8PeGm1bV3ttQT7RZWFx519JKuReXvXv1RM8fn3r1GopTc43asdWOw0MNU5Iy5tF/X6+j11MuPQrVLfyHlupENktixMzKWQAjOVwQ5yfmGDUXiTw3ZeJ9A1DSLxpVhvY1R2RzlSp3KR24IB9+9bNFaHGcH4D8Q3sNzN4M8R7U13TYx5UoGFvbccLKnvjgj/64HeVyfjnwk/iOygvdNm+yeINNbztPuxxtbujeqN0I/wDrgzeCfFyeKtKkM8JtNWs38jULJuGglHXj+6cEg/4GgDpqK5LXfiV4X0Gf7JJf/bNQJ2rZWCmeYt6YXgH6kVkf2p8RvFBxpmlWvhiwbpdal++uSPVYhwp9m/OgCT4L/J8M7K3/AOfe4uYsemJnP9a7S91bTdNXdf6ha2q9czzKg/U15V4Y+GFjLLq2k3/iPXpXsLvbJbw3phhkEiLIJPLUcbtxB56qa6yy+Engaxbevh+CeTOS907zFj77yRQBFr3xb8HaRp11JDrtleXaRMYYbdzL5jgfKuVyBk4GSarfCy50zTdBsNHk1COXXtRtzrNyveUzHJbPQkcA4PauytfD+i2MTRWmkWFvGylWSG2RAQeCCAOleKeKvC0/g3WLS2tbk2mnvcGbQNSY8adcnlraQ/8APGT36e/zZAPWk8MuPiJL4pe6VlbTBp8cGzlB5m8tnPOT7V0Vcz4J8XR+K9KkaaE2mrWb+RqFk3DQSjrx/dOCQf8AA101ABXnvxV1NzaaT4btrp7abVroNPPGxVobWH95K4I5GAB+tehV8/eLb2fxX4u1b7G+XvblPDOnMOdqAh7uX6Dhc+j0Adv8M9Fttasb7xhqthDNeazdvPbm4jDtDbr8kSgnJHC9e4xXpKqqKFUAKOAAOBUFjZQadp9tY2qBLe2iWKJR2VRgD8hVigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAMDXtOgGpadrKCQX9vIIIwjhBKHONrnB+UE56Z645rSsL2W5kuYLiJYp7dwrBH3KQVDAgkD16Y7VjeItReXWdL8P2sUcs1y/n3BYsPJhQ53AqQQ24Dac9RW9aWUNkjiEOTI293dy7M2AMknnoAPwrKPxvl+Z3VdMPD2m7Xu+l/y36FisDVtPnmur8rYrdi7tVgjYsoETDfndk5C/MDlcng8cCt+irlFSVmc1GrKlLmX9dRkKNHCiMxdlUAsf4jjrT6ht7mO6jEkW/YQCCyFcg+mamqrW0MVJS95BRRRQMK808QeC9I8V/E6SN3vbcR6Yr6kbO48oXO6TESSY5PCSE+wT0r0skAEk4A71558Lrsa9deKvFOSRqOpeTD/1xhQLH+jGgDrNC8LaF4ag8nRtKtbMEYZo0+dh/tMfmb8TWvRRQB57c6guhfG+2gbKW+v6YEJJwpnhZip+uw4/EV6FXkHx5Fzp1l4a8SWZxNpmojbgZOWG4f8Aov8AWvTtH13TtdthNYXUUpCI8kauC0W9QwDgdDg9DQBo1n63otj4h0a50rUoRNaXKbHU9R6EHsQeQfUVoUUAeC2cN54O8fWkGq61a6df2ihBqN62yHVtP6bXPTzkwAPXj0BPoN18YPA9vJ5UesfbJu0dnBJKT9CFx+tdVqWh6TrPk/2ppllfeSSYvtMCybCeuNwOOg/KrFrY2ljH5dnawW8f92GMIPyFAHDf8LOubzjSPA3ie7z92Sa1EEbfRmP9Ky/A/hLVP+ExTWdS8ORaDpun20kenWIuxcMJZW3SSlhnkgkc4wMDtXqlFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFQXt5b6fY3F7dSCK3t42llduiqoyT+QqesrxHoFp4o0K40e+knS1uNokMD7GIDA4zjocc0Ac58OftetW154v1KARXGrSE2sZHMVqDiMH3PU44PBruKZDDHbwRwQoscUahERRgKoGABT6SSWxc6kpu8nfZfJaIKKKKZBlSwXemWMAsIo5vKAEyYw0gAxlfQ1asNSttSh3wP8y8PG3DIfQirdcb4s8FS6nfx6/oF+2l+I7ZNsc+SYp0zny5V6FT64yPfFU5XWu5jGk4S91+72/wAjsqK8r0Dxt8QPGWkQXOi+HtHtImyjX95ds8TspKsUjUbsZBxnI46mtI+AvEus8+JPHeoNE3W10mNbRB7bhlmH1qTYn+LPiu28N+BNSVbqJL+6j+zQRFhuO/gtjOeF3HPsKn+E2nHTPhhocTRhHlgNw2O/mMXB/IisrVfhdoekeHLyTw94Z07UdV25A1RmmMwz8wDMflYjIBGMHFcx4F8cp4XjjtbqWd/CzzfZ0e55n0af/n3n77M52v8A4EAA9wopFZXQOjBlYZBByCKWgDyr4radJceINDR5GNnq0FzpEiM3yLM6boGA6bt46+1ZPwo1WQ+KreZw2zXNFiMpI/5erVjCwPoSqlvxruvifYyXXgW7urdVN1pzpfwErna0ZyT/AN87q8ziv00zXk1KJiLfT9Yhv4iT92zvoxuA9lwo/GvUwWWPFU3UUrb6eelvvbS+/sRKfK7HvtFFFeWWFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABXMfEPWToHw/wBb1BW2yrbNHER18x/kX9WBrp681+K17FLfeGdFmP8Ao8l4+o3g/wCne2QyMD7H+lAGZ8KtH8jxXqTEfu9D0620dD2MuPNn/ESE/nXrtcL8JLKaHwFBqN0MXmrzy6lOfVpGyD/3yFruqACvO/HngOW9nm8Q+HoIW1UxGO8sZR+51OHvG4/vejdcgcjAI9EooA8Q8DeOU8Lpb2d1JcSeGJ5/ssLXGTPpNx/z7TDqV67W9B7ED2+vOPHdtBqnjPwj4bigjCXN+2q3oVAN6wJxv9dx+Xn0Fej0ARXNvFd2s1tOu+KZDG6nupGCPyrzm6s4PDWo3UVpZwmxjS0sIneISPD8ysoZmBJViSOejBMdePS6aY0bOUU5xnI646V1YbFOjdPWL6fMlxuOooorlKCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAKD6vbIrSFZfJVwnm7MITvCdT2BPX2OM1Qn8YaRHIYreWW9m/552kZkJ/Hp+tW/7KfyPspuENqJVkVDF8wxIHwTnBHBHT86vwW8FtGI7eGOJB/DGoUfkK57Vns0vlf9TltiJbNL5X+7U4i+17x/f3j2+heFbO0txjbfardcHIB/1SfMMZ/SuU8R+HfE+kXy+LPEr23iWzFrJZahY2kBhNvaucs0WDlsc5zg49uR7NR1rdXS1OlJpWZm+H7zSr7w/Yz6JLHJpnkqtuYzkBFGAvPIIxjB5GOa0q8x1XSr74aapP4i8O273Ph24bzNV0mPrAe88I7Y7r/T7vS6j4+0iy0Ow1a0hvtVgv8AItl023MzuQORjjB9jjkH0pjOporyTWPinr8IYJpWk6An8MmvX480j/r3jzJ/OsTRvGHijUtYg1G1u9e8SeUSVttP05bOwbIIw0r/ADEc55XtQB2nh7/id/GHxNq5+aHSraHSoG7bj+8k/ENx+NehVyHw30DUNB8MSHWY0j1bULua+vFRgwEkjdMjg8BeldfQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAHUYNeezfCLSn1O7lttY1qw026fzZNLsbsxW5kPU4A6H0/pgV6FRQBzGjfDvwhoO1rDQLISryJpk82TPrufJFdP0oooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/2Q==\n"
          },
          "metadata": {},
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from QEPPI import QEPPI_Calculator, get_qeppi_properties\n",
        "\n",
        "q = QEPPI_Calculator()\n",
        "q.read()\n",
        "\n",
        "props = get_qeppi_properties(mol)\n",
        "\n",
        "print(q.qeppi(mol))\n",
        "print(props)"
      ],
      "metadata": {
        "id": "ztBo1M0I95b3",
        "outputId": "65283c3d-d616-41e7-a03c-97131998d256",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "0.7862842663145835\n",
            "{'MW': 615.1503182080002, 'ALOGP': 6.9388800000000055, 'HBD': 3, 'HBA': 5, 'TPSA': 111.45000000000002, 'ROTB': 7, 'AROM': 3}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MNIh6cFLH_0B"
      },
      "source": [
        "# Calculation QEPPI for Your \"SDF file\"\n",
        "If you upload the SDF, the result of calculating QEPPI will be returned as CSV with SMILES."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "k5zXO7IRToX_",
        "outputId": "d31baadd-9329-4574-f33d-31be81538633",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 271
        }
      },
      "source": [
        "from google.colab import files\n",
        "\n",
        "print(\"Please your SDF file upload\")\n",
        "uploaded = files.upload()\n",
        "file_name = list(uploaded.keys())[0]\n",
        "!python calc_QEPPI.py --sdf $file_name\n",
        "!rm -rf $file_name\n",
        "files.download(\"result.csv\")"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Please your SDF file upload\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ],
            "text/html": [
              "\n",
              "     <input type=\"file\" id=\"files-bbbe29e5-5328-4979-8099-3ff40e977db9\" name=\"files[]\" multiple disabled\n",
              "        style=\"border:none\" />\n",
              "     <output id=\"result-bbbe29e5-5328-4979-8099-3ff40e977db9\">\n",
              "      Upload widget is only available when the cell has been executed in the\n",
              "      current browser session. Please rerun this cell to enable.\n",
              "      </output>\n",
              "      <script>// Copyright 2017 Google LLC\n",
              "//\n",
              "// Licensed under the Apache License, Version 2.0 (the \"License\");\n",
              "// you may not use this file except in compliance with the License.\n",
              "// You may obtain a copy of the License at\n",
              "//\n",
              "//      http://www.apache.org/licenses/LICENSE-2.0\n",
              "//\n",
              "// Unless required by applicable law or agreed to in writing, software\n",
              "// distributed under the License is distributed on an \"AS IS\" BASIS,\n",
              "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
              "// See the License for the specific language governing permissions and\n",
              "// limitations under the License.\n",
              "\n",
              "/**\n",
              " * @fileoverview Helpers for google.colab Python module.\n",
              " */\n",
              "(function(scope) {\n",
              "function span(text, styleAttributes = {}) {\n",
              "  const element = document.createElement('span');\n",
              "  element.textContent = text;\n",
              "  for (const key of Object.keys(styleAttributes)) {\n",
              "    element.style[key] = styleAttributes[key];\n",
              "  }\n",
              "  return element;\n",
              "}\n",
              "\n",
              "// Max number of bytes which will be uploaded at a time.\n",
              "const MAX_PAYLOAD_SIZE = 100 * 1024;\n",
              "\n",
              "function _uploadFiles(inputId, outputId) {\n",
              "  const steps = uploadFilesStep(inputId, outputId);\n",
              "  const outputElement = document.getElementById(outputId);\n",
              "  // Cache steps on the outputElement to make it available for the next call\n",
              "  // to uploadFilesContinue from Python.\n",
              "  outputElement.steps = steps;\n",
              "\n",
              "  return _uploadFilesContinue(outputId);\n",
              "}\n",
              "\n",
              "// This is roughly an async generator (not supported in the browser yet),\n",
              "// where there are multiple asynchronous steps and the Python side is going\n",
              "// to poll for completion of each step.\n",
              "// This uses a Promise to block the python side on completion of each step,\n",
              "// then passes the result of the previous step as the input to the next step.\n",
              "function _uploadFilesContinue(outputId) {\n",
              "  const outputElement = document.getElementById(outputId);\n",
              "  const steps = outputElement.steps;\n",
              "\n",
              "  const next = steps.next(outputElement.lastPromiseValue);\n",
              "  return Promise.resolve(next.value.promise).then((value) => {\n",
              "    // Cache the last promise value to make it available to the next\n",
              "    // step of the generator.\n",
              "    outputElement.lastPromiseValue = value;\n",
              "    return next.value.response;\n",
              "  });\n",
              "}\n",
              "\n",
              "/**\n",
              " * Generator function which is called between each async step of the upload\n",
              " * process.\n",
              " * @param {string} inputId Element ID of the input file picker element.\n",
              " * @param {string} outputId Element ID of the output display.\n",
              " * @return {!Iterable<!Object>} Iterable of next steps.\n",
              " */\n",
              "function* uploadFilesStep(inputId, outputId) {\n",
              "  const inputElement = document.getElementById(inputId);\n",
              "  inputElement.disabled = false;\n",
              "\n",
              "  const outputElement = document.getElementById(outputId);\n",
              "  outputElement.innerHTML = '';\n",
              "\n",
              "  const pickedPromise = new Promise((resolve) => {\n",
              "    inputElement.addEventListener('change', (e) => {\n",
              "      resolve(e.target.files);\n",
              "    });\n",
              "  });\n",
              "\n",
              "  const cancel = document.createElement('button');\n",
              "  inputElement.parentElement.appendChild(cancel);\n",
              "  cancel.textContent = 'Cancel upload';\n",
              "  const cancelPromise = new Promise((resolve) => {\n",
              "    cancel.onclick = () => {\n",
              "      resolve(null);\n",
              "    };\n",
              "  });\n",
              "\n",
              "  // Wait for the user to pick the files.\n",
              "  const files = yield {\n",
              "    promise: Promise.race([pickedPromise, cancelPromise]),\n",
              "    response: {\n",
              "      action: 'starting',\n",
              "    }\n",
              "  };\n",
              "\n",
              "  cancel.remove();\n",
              "\n",
              "  // Disable the input element since further picks are not allowed.\n",
              "  inputElement.disabled = true;\n",
              "\n",
              "  if (!files) {\n",
              "    return {\n",
              "      response: {\n",
              "        action: 'complete',\n",
              "      }\n",
              "    };\n",
              "  }\n",
              "\n",
              "  for (const file of files) {\n",
              "    const li = document.createElement('li');\n",
              "    li.append(span(file.name, {fontWeight: 'bold'}));\n",
              "    li.append(span(\n",
              "        `(${file.type || 'n/a'}) - ${file.size} bytes, ` +\n",
              "        `last modified: ${\n",
              "            file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() :\n",
              "                                    'n/a'} - `));\n",
              "    const percent = span('0% done');\n",
              "    li.appendChild(percent);\n",
              "\n",
              "    outputElement.appendChild(li);\n",
              "\n",
              "    const fileDataPromise = new Promise((resolve) => {\n",
              "      const reader = new FileReader();\n",
              "      reader.onload = (e) => {\n",
              "        resolve(e.target.result);\n",
              "      };\n",
              "      reader.readAsArrayBuffer(file);\n",
              "    });\n",
              "    // Wait for the data to be ready.\n",
              "    let fileData = yield {\n",
              "      promise: fileDataPromise,\n",
              "      response: {\n",
              "        action: 'continue',\n",
              "      }\n",
              "    };\n",
              "\n",
              "    // Use a chunked sending to avoid message size limits. See b/62115660.\n",
              "    let position = 0;\n",
              "    do {\n",
              "      const length = Math.min(fileData.byteLength - position, MAX_PAYLOAD_SIZE);\n",
              "      const chunk = new Uint8Array(fileData, position, length);\n",
              "      position += length;\n",
              "\n",
              "      const base64 = btoa(String.fromCharCode.apply(null, chunk));\n",
              "      yield {\n",
              "        response: {\n",
              "          action: 'append',\n",
              "          file: file.name,\n",
              "          data: base64,\n",
              "        },\n",
              "      };\n",
              "\n",
              "      let percentDone = fileData.byteLength === 0 ?\n",
              "          100 :\n",
              "          Math.round((position / fileData.byteLength) * 100);\n",
              "      percent.textContent = `${percentDone}% done`;\n",
              "\n",
              "    } while (position < fileData.byteLength);\n",
              "  }\n",
              "\n",
              "  // All done.\n",
              "  yield {\n",
              "    response: {\n",
              "      action: 'complete',\n",
              "    }\n",
              "  };\n",
              "}\n",
              "\n",
              "scope.google = scope.google || {};\n",
              "scope.google.colab = scope.google.colab || {};\n",
              "scope.google.colab._files = {\n",
              "  _uploadFiles,\n",
              "  _uploadFilesContinue,\n",
              "};\n",
              "})(self);\n",
              "</script> "
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Saving cdk2.sdf to cdk2.sdf\n",
            "QEPPI.model LOADING...\n",
            "SDF LOADING...\n",
            "Caculating QEPPI...\n",
            "Print head 5 rows\n",
            "                                 SMILES     QEPPI\n",
            "0       CC(C)C(=O)COc1nc(N)nc2[nH]cnc12  0.612529\n",
            "1     Nc1nc(OC[C@@H]2CCCO2)c2nc[nH]c2n1  0.589674\n",
            "2  Nc1nc(OC[C@H]2CCC(=O)N2)c2nc[nH]c2n1  0.507818\n",
            "3         Nc1nc(OCC2CCCCC2)c2nc[nH]c2n1  0.667538\n",
            "4   Nc1nc(OC[C@@H]2CC=CCC2)c2nc[nH]c2n1  0.663518\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ],
            "application/javascript": [
              "\n",
              "    async function download(id, filename, size) {\n",
              "      if (!google.colab.kernel.accessAllowed) {\n",
              "        return;\n",
              "      }\n",
              "      const div = document.createElement('div');\n",
              "      const label = document.createElement('label');\n",
              "      label.textContent = `Downloading \"${filename}\": `;\n",
              "      div.appendChild(label);\n",
              "      const progress = document.createElement('progress');\n",
              "      progress.max = size;\n",
              "      div.appendChild(progress);\n",
              "      document.body.appendChild(div);\n",
              "\n",
              "      const buffers = [];\n",
              "      let downloaded = 0;\n",
              "\n",
              "      const channel = await google.colab.kernel.comms.open(id);\n",
              "      // Send a message to notify the kernel that we're ready.\n",
              "      channel.send({})\n",
              "\n",
              "      for await (const message of channel.messages) {\n",
              "        // Send a message to notify the kernel that we're ready.\n",
              "        channel.send({})\n",
              "        if (message.buffers) {\n",
              "          for (const buffer of message.buffers) {\n",
              "            buffers.push(buffer);\n",
              "            downloaded += buffer.byteLength;\n",
              "            progress.value = downloaded;\n",
              "          }\n",
              "        }\n",
              "      }\n",
              "      const blob = new Blob(buffers, {type: 'application/binary'});\n",
              "      const a = document.createElement('a');\n",
              "      a.href = window.URL.createObjectURL(blob);\n",
              "      a.download = filename;\n",
              "      div.appendChild(a);\n",
              "      a.click();\n",
              "      div.remove();\n",
              "    }\n",
              "  "
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ],
            "application/javascript": [
              "download(\"download_dfb81591-131f-4ba5-a47c-167e436d4544\", \"result.csv\", 3113)"
            ]
          },
          "metadata": {}
        }
      ]
    }
  ]
}